package com.yanfei.zero.infrastructure.redis;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Component
@Aspect
@Slf4j
public class RateLimiterAspect {

    private static final String REDIS_KEY_PREFIX = "rate_limiter:";
    private static final int DEFAULT_RATE = 10; // 默认速率为10个请求/秒
    private static final int DEFAULT_CAPACITY = 100; // 默认桶容量为100个令牌

	@Autowired
	private RedissonClient redissonClient;

    @Autowired
    public RateLimiterAspect(RedissonClient redisson) {
        this.redissonClient = redisson;
    }

    @Around("@annotation(com.yanfei.zero.infrastructure.redis.RateLimiter)")
    public Object rateLimit(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature ms = (MethodSignature)joinPoint.getSignature();
        
    	RateLimiter rateLimiter =  ms.getMethod().getAnnotation(RateLimiter.class);
    	
        String key = REDIS_KEY_PREFIX + rateLimiter.key();
        int rate = rateLimiter.rate() > 0 ? rateLimiter.rate() : DEFAULT_RATE;
        int capacity = rateLimiter.capacity() > 0 ? rateLimiter.capacity() : DEFAULT_CAPACITY;

        RRateLimiter rRateLimiter = redissonClient.getRateLimiter(key);
        rRateLimiter.trySetRate(RateType.OVERALL, rate, 1, RateIntervalUnit.SECONDS);
        rRateLimiter.trySetRate(RateType.PER_CLIENT, rate, capacity, RateIntervalUnit.SECONDS);

        boolean acquired = rRateLimiter.tryAcquire();
        if (acquired) {
            return joinPoint.proceed();
        } else {
            log.warn("Rate limit exceeded for key: {}", key);
            throw new RuntimeException("Rate limit exceeded");
        }
    }
}
